﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.ServiceProcess;
using System.Text;
using System.Threading;
using System.IO;

namespace Cron
{
    public partial class Cron : ServiceBase
    {

        Thread thread;

        public const string dateformat = "yyyy-MM-dd HH:mm:ss";
        //规则文件以及log的默认路径和大小
        private static string logPath;

        public Cron()
        {
            InitializeComponent();
        }

        private string crontabPath = $"{System.Threading.Thread.GetDomain().BaseDirectory}crontab";

        private List<string> Rules
        {
            get
            {
                try
                {
                    List<string> rules = new List<string>();
                    StreamReader sr = new StreamReader(crontabPath, Encoding.GetEncoding("GB2312"));

                    string rule;
                    do
                    {

                        rule = sr.ReadLine();

                        if (!string.IsNullOrEmpty(rule))
                        {
                            rules.Add(rule);
                            //LogWritter( string.Format("配置记录 {0}", rule));
                        }
                    } while (!string.IsNullOrEmpty(rule));

                    LogWritter($"读取配置文件完成,排程{rules.Count.ToString()}笔数");

                    sr.Close();
                    return rules;
                }
                catch (Exception err)
                {
                    LogWritter(string.Format("配置文件读取错误{0}", err.Message));
                }
                return null;

            }
        }
        /// <summary>
        /// 服务启动
        /// </summary>
        /// <param name="args"></param>
        protected override void OnStart(string[] args)
        {

            LogWritter(string.Format(@"配件文件{0}", crontabPath));
            //Timer timer;
            //TimeSpan interval = TimeSpan.FromMinutes(1);
            //timer = new Timer(new TimerCallback(obj => RefreshTask()), null, interval, interval);

            thread = new Thread(() => run());
            thread.Start();

            LogWritter(@"Windows定时服务:服务开始时间");
        }

        /// 服务停止
        protected override void OnStop()
        {
            thread.Abort();
            LogWritter(@"Windows定时服务: 服务停止时间");
        }


        private void run()
        {
            Thread.Sleep((60 - DateTime.Now.Second) * 1000); //计算整分钟
            while (true)
            {
                new Thread(() => RefreshTask()).Start();
                new Thread(() => SendRetryTask()).Start();
                Thread.Sleep((60 - DateTime.Now.Second) * 1000);               
            }
        }

        /// 刷新并判断是否有要运行的规则
        private void RefreshTask()
        {
            try
            {

                Stopwatch sw = new Stopwatch();
                sw.Start();
                DateTime recdatetime = DateTime.Now;
                LogWritter(string.Format("开始执行{0}时间 *****************************************", recdatetime));
                foreach (var rule in Rules)
                {
                    string[] args = rule.Split(' ');
                    string filename = args[5];
                    string para1=null;
                    if (args.Length>6) para1 = args[6];

                  //  LogWritter(string.Format("---取规则数据{0}", rule.ToString()));

                    if (CronExtension.CompareDateTime(recdatetime, args[0], args[1], args[2], args[3], args[4]))
                    {
                        if (para1==null)
                        {
                            Stopwatch stopwatch1 = new Stopwatch();
                            stopwatch1.Start();
                            LogWritter(string.Format("程序执行开始 {0}.\n", filename));
                            System.Diagnostics.Process.Start(filename);
                            stopwatch1.Stop();
                            LogWritter(string.Format("程序执行结束 {0},用时{1}毫秒.\n", filename,stopwatch1.ElapsedMilliseconds));
                        }
                        else
                        {
                            Stopwatch stopwatch2 = new Stopwatch();
                            stopwatch2.Start();
                            LogWritter(string.Format("程序执行 {0} {1}.\n", filename, para1));
                            System.Diagnostics.Process.Start(filename, para1);
                            stopwatch2.Stop();
                            LogWritter(string.Format("程序执行 {0} {1},用时{2}毫秒.\n", filename, para1, stopwatch2.ElapsedMilliseconds));
                        }

                    }
                }
                sw.Stop();
                LogWritter(string.Format("执行一次,用时{0}毫秒 ========================================\n\n", sw.ElapsedMilliseconds));
            }
            catch (Exception e)
            {
                LogWritter("**************** 错误信息********************");
                LogWritter(e.Message);
                LogWritter("*********************************************");
            }
        }

        private void SendRetryTask()
        {
            try
            {
                Stopwatch sw = new Stopwatch();
                sw.Start();
                DateTime recdatetime = DateTime.Now;
                LogRetryWritter(string.Format("重式排程开始执行{0}时间 *****************************************", recdatetime));
                string baseDirectory = System.Threading.Thread.GetDomain().BaseDirectory + "SendRetry";
                var files = Directory.GetFiles(baseDirectory, $"*.txt");
                LogRetryWritter("重式排程文件总数：" + files.Length);
                foreach (var file in files)
                {
                    string str = null;
                    using (StreamReader streamReader = new StreamReader(file, Encoding.GetEncoding("GB2312")))
                    {
                        str = streamReader.ReadLine();
                        if (str == null)
                        {
                            LogRetryWritter("重式排程文件内容为空:" + file);
                            continue;
                        }

                        string[] rule = str.Split(' ');
                        if (rule.Length < 4)
                        {
                            LogRetryWritter("重试排程参数有误:" + str);
                            continue; 
                        }

                        if (recdatetime.ToString("yyyyMMdd-HH:mm") == rule[0])
                        {
                            Stopwatch stopwatch2 = new Stopwatch();
                            stopwatch2.Start();
                            LogRetryWritter(string.Format("重试程序执行 {0} {1}.\n", rule[1], rule[2]));
                            System.Diagnostics.Process.Start(rule[1], rule[2]);
                            stopwatch2.Stop();
                            LogRetryWritter(string.Format("重试程序执行 {0} {1},用时{2}毫秒.\n", rule[1], rule[2], stopwatch2.ElapsedMilliseconds));
                        }

                    }
                }
                sw.Stop();
                LogRetryWritter(string.Format("执行一次,用时{0}毫秒 ========================================\n\n", sw.ElapsedMilliseconds));
            }
            catch (Exception e)
            {
                LogWritter("****************重试发送错误信息********************");
                LogWritter(e.Message);
                LogWritter("*********************************************");
            }
        }


        private static void LogWritter(string text)
        {
            logPath = $"{System.Threading.Thread.GetDomain().BaseDirectory}\\Log\\{DateTime.Now.ToString("yyyyMMdd")}_cron.log";
            FileStream fs = new FileStream(logPath, FileMode.OpenOrCreate, FileAccess.Write, FileShare.ReadWrite);
            StreamWriter m_streamWriter = new StreamWriter(fs);
            m_streamWriter.BaseStream.Seek(0, SeekOrigin.End);
            m_streamWriter.WriteLine($"[{DateTime.Now.ToString(dateformat)}] {text}");
            m_streamWriter.Flush();
            m_streamWriter.Close();
            fs.Close();
        }

        private static void LogRetryWritter(string text)
        {
            logPath = $"{System.Threading.Thread.GetDomain().BaseDirectory}\\Log\\{DateTime.Now.ToString("yyyyMMdd")}_Retry.log";
            FileStream fs = new FileStream(logPath, FileMode.OpenOrCreate, FileAccess.Write, FileShare.ReadWrite);
            StreamWriter m_streamWriter = new StreamWriter(fs);
            m_streamWriter.BaseStream.Seek(0, SeekOrigin.End);
            m_streamWriter.WriteLine($"[{DateTime.Now.ToString(dateformat)}] {text}");
            m_streamWriter.Flush();
            m_streamWriter.Close();
            fs.Close();
        }
    }
}
